import os # needed for file access
import hashlib # needed for md5sum
try:
  import ConfigParser as configparser # For python < 3.0
except:
  import configparser # for python 3.0+
import subprocess # for running external code

# This is where the photos are stored
if os.name == 'posix':
  # If we are on linux
  baseDirectory = '/home/owain/Pictures/2011-03-19 Owain in Boston'
  DoNot = False
else:
  #Assume we are in windows
  baseDirectory = 'c:\Photos'
  DoNot = True

# These are the datatypes we put in the picasascript file
dataTypeList = ['album','filename','md5sum','uploaded','date','tags']

# Definitions

def CreatePicasascriptDirectory(directory):
  # Generate the full directory name
  fullDirectory = os.path.join(directory,'.picasascript')
  # Check to see if it already exists and is writable
  if os.path.isdir(fullDirectory) and os.access(fullDirectory,os.W_OK) == True:
    print(fullDirectory+' already exists and is writable.')
    return
  # If not try and make the directory
  try:
    os.mkdir(fullDirectory)
  except:
    print('Cannot create .picasascript in the '+directory+' directory')
    exit(1)
  else:
    print('Created '+fullDirectory+' directory')

def GetPicasascriptDataFile(directory,filename):
  print(directory,filename)
  # Create a .picasascript directory
  CreatePicasascriptDirectory(directory)
  # Generate a filename with picasascript at it's end
  dataFilename = filename+'.picasascript'
  # Generate full filename
  fullFilename = os.path.join(directory,'.picasascript',dataFilename)
  # Set the test to be negative
  photoConfigLoaded = False
  # Check to see if it already exists and is writable
  if os.path.isfile(fullFilename):
    print(fullFilename+' already exists')
    if os.access(fullFilename,os.W_OK) == True:
      print(fullFilename+' can be written')
    else:
      print('Warning read only file at '+fullFilename)
      exit(1)
    try:
      # Try and load the data
      loadedConfig = configparser.SafeConfigParser()
      loadedConfig.read(fullFilename)
      photoConfigLoaded = True
    except:
      photoConfigLoaded = False
  
  # Test to see if the filename is correct in the file
  if photoConfigLoaded == True:
    if loadedConfig.get('config','filename') == filename:
      return loadedConfig      
  
  # Assume data loading went wrong make a new one
  print('photoConfig file is corrupted, making new one')
  # Create the default photoConfig
  photoConfig = configparser.SafeConfigParser()
  # Create blank values
  CreateBlankPhotoConfigTemplate(photoConfig)
  return photoConfig

def CreateBlankPhotoConfigTemplate(photoConfig):
  photoConfig.add_section('config')
  for dataType in dataTypeList:
    photoConfig.set('config',dataType,'')
  return photoConfig  

def AddDataPicasascriptDataFile(photoConfig,datatype,data):
  #Create validDatatype test
  for dataType in dataTypeList:
    if dataType == datatype:
      photoConfig.set('config',datatype,data)
      validDatatype = True;
  if validDatatype != True:
    print('Invalid datatype : '+datatype+' not adding.')
  return

def SavePicasascriptDataFile(photoConfig,directory,filename):
  # Create a .picasascript directory
  CreatePicasascriptDirectory(directory)
  # Generate a filename with picasascript at it's end
  dataFilename = filename+'.picasascript'
  # Generate full filename
  fullFilename = os.path.join(directory,'.picasascript',dataFilename)
  # Try and write to file
  print('Creating '+fullFilename)
  try:
    fileOut = open(fullFilename,'w')
    photoConfig.write(fileOut)
    fileOut.close()
  except:
    print('Cannot create '+dataFilename+' in the '+directory+'\.picasascript directory')
    exit(1)
    
def GetMd5sum(filename):
  # Open file, rb - r read only, b - binary needed for windows
  infile = open(filename,'rb')
  # Read into a temporary variable
  content = infile.read()
  # Close the file
  infile.close()
  # Calculate md5 sum and return
  md5sum = hashlib.md5()
  md5sum.update(content)
  return md5sum.hexdigest()

def GoogleCheckAlbum(albumname):
  if DoNot: return
  # Check to see if the albumname exists
  process = subprocess.Popen(['google', 'picasa', 'list-albums','--title='+albumname], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  #Check for errors
  answer = process.communicate()
  print answer
  if answer[1] != '':
    print('Error checking album - '+answer[1])
    exit(1)
  # If there are no errors - should get 'albumname, https://'
  if answer[0].partition(',')[0] == albumname:
    print('Album : "'+albumname+'" already exists')
    return
  print('No matching album found - making one')
  GoogleCreateAlbum(albumname)
  exit(0)

def GoogleCreateAlbum(albumname):
  if DoNot: return
  # Check to see if the albumname exists
  process = subprocess.Popen(['google', 'picasa', 'create','--title='+albumname], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  #Check for errors
  answer = process.communicate()
  # If there are no errors - should get 'Created album: https://...'
  if answer[1].partition(':')[0] != 'Created album':
    print('Error creating album - '+answer[0])
    exit(1)
    
def GoogleUploadPicture(albumname,photoPath,filename):
  print('Uploading file : '+filename+' to : '+albumname)
  if DoNot: return
  # Upload photo
  process = subprocess.Popen(['google', 'picasa', 'post','--title='+albumname,'--src='+photoPath], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  print( process.communicate())

def ProcessFiles(directory,albumname):
  # Iterate through the files and start making a list of files to upload
  listOfFiles = os.listdir(directory)
  # Sort the list - I like to do things in order.
  listOfFiles.sort()
  # Check to see that an album exixts if not create one
  GoogleCheckAlbum(albumname)
  for photoFileName in listOfFiles:
    # We need to remember to use the full path
    photoFileFullPath = os.path.join(directory,photoFileName)
    # If it is a file open it and calculate the md5 sum of the file
    if os.path.isfile(photoFileFullPath) == True:
      # Only open it if the file ends with .JPG, .jpg or .jpeg(case sensitivity needed for linux)
      fileEnding = os.path.splitext(photoFileName)[1]
      if fileEnding == '.JPG' or fileEnding ==  '.jpg' or fileEnding == '.jpeg':
        print('Evaluating: '+photoFileFullPath)
        # Create a .picasascript directory and create datastore
        photoConfig = GetPicasascriptDataFile(directory,photoFileName)
        # Calculate md5 of file
        photoFileMd5sum = GetMd5sum(photoFileFullPath)
        # Check to see if the md5 sums are the same
        if photoConfig.get('config','md5sum') != photoFileMd5sum:
          print('md5 of '+photoFileFullPath+' is not the same, uploading')
          GoogleUploadPicture(albumname,photoFileFullPath,photoFileName)
          # Update local datafile
          AddDataPicasascriptDataFile(photoConfig,'filename',photoFileName)
          AddDataPicasascriptDataFile(photoConfig,'md5sum',photoFileMd5sum)
          AddDataPicasascriptDataFile(photoConfig,'uploaded','True')
          AddDataPicasascriptDataFile(photoConfig,'date','')
          SavePicasascriptDataFile(photoConfig,directory,photoFileName)
        else:
          print('md5 sum the same. nothing to do')

def ProcessDirectory(directory, albumname):
  # Make a list of files and directories
  directoryList = os.listdir(directory)
  # Sort the list - I like doing things alphabetically
  directoryList.sort()
  # Iterate through the files and start uploading files if needed
  for photoDirectory in directoryList:
    # We need use the full path
    photoDirectoryFullPath = os.path.join(directory,photoDirectory)
    # If it is a directory process it
    if os.path.isdir(photoDirectoryFullPath) == True:
      # Make sure we don't process the .picasascript directory
      if photoDirectory == '.picasascript':
        continue
      # Create a sensible subAlbumName with colons between directories
      if albumname != '':
        subAlbumName = albumname+':'+photoDirectory
      else:
        subAlbumName = photoDirectory
      # Process files in the directory
      ProcessFiles(photoDirectoryFullPath,subAlbumName)
      # Now if there are sub directories - do it again
      ProcessDirectory(photoDirectoryFullPath,subAlbumName)
      
# Start of Code proper

# Test to see if the photos directory is import
if os.path.isdir(baseDirectory) == True:
  print('I can find the directory: '+baseDirectory)
else:
  print('Cannot find the photo directory: '+baseDirectory)
  exit(1)

# Test to see if the photos directory is writable and create a picasascript directory
if os.access(baseDirectory,os.W_OK) == True:
  print('I can write to the directory - good!')
else:
  print('Cannot write to the photo directory')
  exit(1)

# Process the baseDirectory
ProcessFiles(baseDirectory,'Root Folder')

# Process the subdirectories
ProcessDirectory(baseDirectory,'')

exit(0)
